package com.treeman.marker.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.treeman.api.json.marker.MarkerJson;
import com.treeman.marker.Marker;
import com.treeman.marker.Marker.MarkerType;
import com.treeman.marker.dao.MarkerDao;
import com.treeman.marker.exception.MarkerNotFoundException;
import com.treeman.marker.exception.NoMarkersFoundException;
import com.treeman.user.User;
import com.treeman.user.dao.UserDao;

@Service
public class MarkerServiceImpl implements MarkerService {

	private static Logger log = Logger.getLogger(MarkerServiceImpl.class);

	@Autowired
	private MarkerDao markerDao;

	@Autowired
	private UserDao userDao;

	@Override
	@Transactional
	public Long addMarker(MarkerJson markerJson) {
		log.debug("<SERVICE> Adding marker: " + markerJson.getName());

		User user = userDao.getUserByUsername(markerJson.getAuthor());
		markerJson.setCreated(new Date());
		Long id = markerDao.addMarker(markerJson.toMarker(user));

		return id;
	}

	@Override
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public List<Marker> getUserMarkers(String username)
			throws NoMarkersFoundException {
		log.debug("<SERVICE> Getting all markers for user: " + username);

		List<Marker> markers = markerDao.getMarkersByUserUsername(username);
		if (markers.size() > 0)
			return markers;
		else
			throw new NoMarkersFoundException(username);
	}

	@Override
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public List<MarkerJson> getUserMarkersJson(String username)
			throws NoMarkersFoundException {
		log.debug("<SERVICE> Getting all jsonMarkers for user: " + username);

		List<Marker> markers = markerDao.getMarkersByUserUsername(username);
		List<MarkerJson> jsonMarkers = new ArrayList<MarkerJson>();
		for (Marker marker : markers) {
			MarkerJson jsonMarker = new MarkerJson(marker);
			jsonMarkers.add(jsonMarker);
		}

		if (markers.size() > 0)
			return jsonMarkers;
		else
			throw new NoMarkersFoundException(username);
	}

	@Override
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public MarkerJson getMarkerJsonById(Long id) throws MarkerNotFoundException {
		log.debug("<SERVICE> Getting jsonMarker id: " + id);
		Marker marker = markerDao.getMarkerById(id);
		if (marker == null)
			throw new MarkerNotFoundException(id);

		MarkerJson jsonMarker = new MarkerJson(marker);
		return jsonMarker;
	}

	@Override
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public Marker getMarkerById(Long id) throws MarkerNotFoundException {
		log.debug("<SERVICE> Getting marker id: " + id);
		Marker marker = markerDao.getMarkerById(id);
		if (marker == null)
			throw new MarkerNotFoundException(id);
		return marker;
	}

	@Override
	@Transactional
	public Long updateMarkerJson(MarkerJson markerJson, String username)
			throws MarkerNotFoundException {

		log.debug("<SERVICE> Updating marker. Id " + markerJson.getId());

		Marker marker = markerDao.getMarkerById(markerJson.getId());
		if (marker == null)
			throw new MarkerNotFoundException(markerJson.getId());

		marker.setDescription(markerJson.getDescription());
		marker.setName(markerJson.getName());
		marker.setType(MarkerType.valueOf(markerJson.getType()));

		return marker.getId();

	}

	@Override
	@Transactional
	public void deleteMarker(Long id, String username)
			throws MarkerNotFoundException {

		Marker marker = markerDao.getMarkerById(id);
		if (marker == null)
			throw new MarkerNotFoundException(id);

		if (marker.getAuthor().getUsername().equals(username) == false)
			throw new AccessDeniedException("Access denied");

		markerDao.deleteMarker(marker);
	}
}
